<h1>Declaring advices</h1>

<p>
    In our previous example, we have already build a before advice thanks to the
    annotation <u>@before</u>. Advices are the actual action, the implementation
    of the concern you want to weave in to some target. Four advice types exist
    in <b>Aspect PHP</b> to intercept method calls:
    Before, After returning, After throwing and Around.
</p>

<h3>Before advice</h3>

<p>
    A <i>before advice</i> allows for executing code before the target method is
    invoked. However, the advice cannot prevent the target method from being
    executed, nor can it have influence on other before advices at the same
    join point.
</p>

<div class="code">
    <code>
        <small>The before advice is invoked before any method call on Foo:</small><br />
        /**<br />
        &nbsp;* <b>@before</b> method(Foo->.*())<br />
        &nbsp;*/<br />
        public function myBeforeAdvice() {<br />
        &nbsp;&nbsp;&nbsp;&nbsp;// Do some before stuff...<br />
        }<br />
    </code>
</div>

<h3>After returning advice</h3>

<p>
    The <i>after returning advice</i> becomes active after the target method normally
    returns from execution (i.e. it doesn't throw an exception). After returning
    advices may read the result of the target method, but can't modify it.
</p>

<div class="code">
    <code>
        <small>The after returning advice is invoked after any successful method call on Foo:</small><br />
        /**<br />
        &nbsp;* <b>@afterReturning</b> method(Foo->.*())<br />
        &nbsp;*/<br />
        public function myAfterReturningAdvice() {<br />
        &nbsp;&nbsp;&nbsp;&nbsp;// Do some after stuff...<br />
        }<br />
    </code>
</div>

<h3>After throwing advice</h3>

<p>
    Similar to the <i>after returning advice</i>, the
    <i>after throwing advice</i> is invoked after method execution, but only if
    an exception was thrown.
</p>

<div class="code">
    <code>
        <small>The after throwing advice is invoked after any method call that threw an exception on Foo:</small><br />
        /**<br />
        &nbsp;* <b>@afterThrowing</b> method(Foo->.*())<br />
        &nbsp;*/<br />
        public function myAfterThrowingAdvice() {<br />
        &nbsp;&nbsp;&nbsp;&nbsp;// Do some after stuff...<br />
        }<br />
    </code>
</div>

<h3>After advice</h3>

<p>
    The <i>after advice</i> is a combination of <i>after returning</i> and
    <i>after throwing</i>: These advices become active after method execution,
    no matter if an exception was thrown or not.
</p>

<div class="code">
    <code>
        <small>The after advice is always invoked after any method call on Foo:</small><br />
        /**<br />
        &nbsp;* <b>@after</b> method(Foo->.*())<br />
        &nbsp;*/<br />
        public function myAfterAdvice() {<br />
        &nbsp;&nbsp;&nbsp;&nbsp;// Do some after stuff...<br />
        }<br />
    </code>
</div>

<h3>Around advice</h3>

<p>
    Finally, the <i>around advice</i> takes total control over the target method
    and intercepts it completely. It may decide to call the original method or
    not and even modify the result of the target method or return a completely
    different one. Obviously the around advice is the most powerful and should
    only be used if the concern can't be implemented with the alternative
    advice types.
</p>

<div class="code">
    <code>
        <small>The around advice intercepts totally any method call on Foo:</small><br />
        /**<br />
        &nbsp;* <b>@around</b> method(Foo->.*())<br />
        &nbsp;*/<br />
        public function myAroundAdvice() {<br />
        &nbsp;&nbsp;&nbsp;&nbsp;// Do some around stuff...<br />
        }<br />
    </code>
</div>

<h2>Implementing advices</h2>

<p>
    This is the last step before you can fully use the advices you've just
    declared. The implementation is located in the advice method as we've
    already seen:
</p>

<div class="code">
    <code>
        <small>An implementation for an after throwing advice:</small><br />
        /**<br />
        &nbsp;* <b>@afterThrowing</b> method(Foo->doSomeStuff())<br />
        &nbsp;*/<br />
        public function myAfterThrowingMethodAdvice(aspectJoinpoint $joinpoint) {<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;$exception = $joinpoint->getException();<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;$message = $exception->getMessage();<br />
        &nbsp;&nbsp;&nbsp;&nbsp;echo $message;<br />
        }<br />
    </code>
</div>

<p class="notice">
    The key parameter here is the <i>aspectJoinpoint</i> class which allows the
    advice to be aware of the current execution context and is accessible for
    all advices (i.e. before, after and around).
</p>

<h3>Accessing join points</h3>

<p>
    The <i>aspectJoinpoint</i> is an interface which defines the following
    methods:
</p>

<table>
    <tbody>
        <tr>
            <th>getClassName()</th>
            <td>
                Returns the name of the target class this join point refers to
            </td>
        </tr>
        <tr>
            <th>getMethodName()</th>
            <td>
                Returns the name of the method this join point refers to
            </td>
        </tr>
        <tr>
            <th>getMethodArguments()</th>
            <td>
                Returns an array of arguments which have been passed to the
                target method
            </td>
        </tr>
        <tr>
            <th>getMethodArgument(<i>$argumentName</i>)</th>
            <td>
                Returns the value of the specified method argument
            </td>
        </tr>
        <tr>
            <th>hasMethodArgument(<i>$argumentName</i>)</th>
            <td>
                Returns <b>true</b> if the argument with the specified name
                exists in the method call this joinpoint refers to
            </td>
        </tr>
        <tr>
            <th>getResult()</th>
            <td>
                Returns the result of the method invocation. The result is only
                available for <i>after returning advices</i>
            </td>
        </tr>
        <tr>
            <th>hasException()</th>
            <td>
                If an exception was thrown by the target method. It only makes
                sense for <i>after throwing advices</i>
            </td>
        </tr>
        <tr>
            <th>getException()</th>
            <td>
                Returns the exception which has been thrown in the target
                method. If no exception has been thrown, null is returned.
                It only makes sense for <i>after throwing advices</i>
            </td>
        </tr>
    </tbody>
</table>

<p class="notice">
    In <b>Aspect PHP</b>, the arguments passed to the method are accessible
    through an array which you can access by giving the name of the argument:
    <code>$jointpoint->getArgument('fooParam')</code> or the order in the
    original method declaration:
    <code>$joinpoint->getArgument(0)</code>.
</p>

<h3>Advice chains</h3>

<p>
    Around advices are a special advice type in that they have the power to
    completely intercept the target method. For any other advice type,
    the advice methods are called by the proxy class one after another. In case
    of the around advice, the methods form a chain where each link is
    responsible to pass over control to the next.
</p>

<div style="text-align: center;">
    <img src="images/advicechain.png" alt="The around advices are chained and
         each advice is responsible for passing over control to the next" />
    <br />
    <small>
        This diagram has been taken from the specifications of the <b>AOP</b>
        framework for <b>FLOW3</b>.
    </small>
</div>

<p>
    Now here's a complete around advice:
</p>

<div class="code">
    <code>
        <small>An around advice example:</small><br />
        /**<br />
        &nbsp;* <b>@around</b> method(Foo->.*())<br />
        &nbsp;*/<br />
        public function myAroundAdvice(aspectJoinpoint $joinpoint, aspectAdviceChain $adviceChain) {<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;// Do some before stuff...<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;$result = $adviceChain->proceed($joinpoint);<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;// Do some after stuff...<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;return $result;<br />
        }<br />
    </code>
</div>

<p class="notice">
    As you can see there is another parameter to our advice which is the
    <i>aspectAdviceChain</i>. This class only defines one method which is:
    <code>proceed(<i>aspectJoinpoint</i> <i>$joinpoint</i>)</code> and allows
    the around advices to take control over the execution of the target method.
</p>

<p class="warning">
    Don't forget to return the result of the method or it will be lost!!
</p>

<p>
    In the next section, we're going to see how to cache <b>Aspect PHP</b>
    configuration to avoid scanning classes for annotations at each request.
</p>